<?php
namespace App\Models\System;

use App\Exceptions\ApiException;
use App\Providers\LengthAwarePaginatorProvider;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use App\Enums\System\SysDept\{Status, DelFlag};

/**
* 部门表 模型
* @create 2023-08-21 17:26:22
*/
class SysDeptModel extends \App\Models\BaseModel {
    use HasFactory;

    const Table			= "sys_dept";
    const PrimaryKey	= "dept_id";
    public $timestamps	= true;

    static $Wheres = ['dept_id', 'parent_id', 'status', 'del_flag'];     // 直接定义column, 默认where(column, '=', value)
    public function __construct($attributes = []) {
        parent::__construct($attributes);

        // static::$Wheres['dept_id']   = fn($q, $v) => $q->where(atn('dept_id'), '=', $v);
        static::$Wheres['dept_name']    = fn($q, $v) => $q->where(atn('dept_name'), 'like', "%{$v}%");
    }

    /** xxxx */
    // public function user() {
        // return $this->hasOne(User::class, 'id', 'uid');
    // }

    /** ========== 常用查询 ========== */
    static $Vo  = ['dept_id','parent_id','ancestors','dept_name','order_num','leader','phone','email','status','del_flag','parent_name','create_by','create_t
    ime','update_by','update_time'];
    static $Voi = ['*', ];

    /**
     * 查询部门管理数据
     * 
     * @param $dept 部门信息
     * @return SysDeptModel[]|Collection 部门信息集合
     */
    public function selectDeptList(array $dept): Collection {
        return $this->selectVo()
            ->where('del_flag', '=', '0')
            ->wheres($dept, 'dept_id', 'parent_id', 'dept_name', 'status')
            ->orderBy(atn('parent_id'))
            ->orderBy(atn('order_num'))
            ->get()
            ;
    }

    /**
     * 根据角色ID查询部门树信息
     * 
     * @param $roleId 角色ID
     * @param bool $deptCheckStrictly 部门树选择项是否关联显示
     * @return int[]|array 选中部门列表
     */
    public function selectDeptListByRoleId(int $roleId, bool $deptCheckStrictly): array {
        return $this
            ->select(atn('dept_id'))
            ->leftJoin(SysRoleDeptModel::Table, SysRoleDeptModel::atn('dept_id'), '=', atn('dept_id'))
            ->where(atn('role_id'), '=', $roleId)
            ->when($deptCheckStrictly, fn($q)=>$q->whereRaw(atn('dept_id') . " not in (select d.parent_id from sys_dept d inner join sys_role_dept rd on d.dept_id = rd.dept_id and rd.role_id = $roleId)"))
            ->orderBy(atn('parent_id'))
            ->orderBy(atn('order_num'))
            ->get()
            ->toArray()
            ;
    }

    /**
     * 根据部门ID查询信息
     * 
     * @param $deptId 部门ID
     * @return SysDeptModel 部门信息
     */
    public function selectDeptById(int $deptId): SysDeptModel {
        $cols = "d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, (select dept_name from sys_dept as b where b.dept_id = d.parent_id) as parent_name";
        $cols = str_replace('d.', static::Table.'.', $cols);
        return throw_str(
            $this
                ->selectRaw($cols)
                ->where(atn('dept_id'), '=', $deptId)
                ->first() 
            ?? "部门({$deptId})查找失败");
    }

    /**
     * 根据ID查询所有子部门
     * 
     * @param $deptId 部门ID
     * @return SysDeptModel[]|Collection 部门列表
     */
    public function selectChildrenDeptById($deptId): Collection {
        return $this
            ->whereRaw("find_in_set($deptId, `ancestors`)")
            ->get()
            ;
    }

    /**
     * 根据ID查询所有子部门（正常状态）
     * 
     * @param $deptId 部门ID
     * @return int 子部门数
     */
    public function selectNormalChildrenDeptById($deptId): int {
        return $this
            ->select(static::PrimaryKey)
            ->where('status', '=', '0')
            ->where('del_flag', '=', '0')
            ->whereRaw("find_in_set($deptId, `ancestors`)")
            ->count()
            ;
    }

    /**
     * 是否存在子节点
     * 
     * @param $deptId 部门ID
     * @return 结果
     */
    public function hasChildByDeptId($deptId): int {
        return $this
            ->select(static::PrimaryKey)
            ->where('del_flag', '=', '0')
            ->where('parent_id', '=', $deptId)
            ->count()
            ;
    }

    /**
     * 查询部门是否存在用户
     * 
     * @param $deptId 部门ID
     * @return 结果
     */
    public function checkDeptExistUser($deptId): int {
        return $this
            ->select(static::PrimaryKey)
            ->where('del_flag', '=', '0')
            ->where('dept_id', '=', $deptId)
            ->count()
            ;
    }

    /**
     * 校验部门名称是否唯一
     * 
     * @param $deptName 部门名称
     * @param $parentId 父部门ID
     * @return SysDeptModel 结果
     */
    public function checkDeptNameUnique($deptName, $parentId): SysDeptModel {
        return throw_str(
            $this->selectVo()
                ->where('del_flag', '=', '0')
                ->where('dept_name', '=', $deptName)
                ->where('parent_id', '=', $parentId)
                ->first() 
            ?? "部门($deptName)查找失败");
    }

    /**
     * 新增部门信息
     * 
     * @param $dept 部门信息
     * @return SysDeptModel 结果
     */
    public function insertDept(array $dept): SysDeptModel {
        $values = static::when(
                    $dept, 
                    'dept_id',
                    'parent_id',
                    'dept_name',
                    'ancestors',
                    'order_num',
                    'leader',
                    'phone',
                    'email',
                    'status',
                    'create_by',
                );
        return throw_str(
            static::row_add($values)
        );
    }

    /**
     * 修改部门信息
     * 
     * @param $dept 部门信息
     * @return int 结果
     */
    public function updateDept(array $dept): int {
        $values = static::when(
                    $dept, 
                    'parent_id',
                    'dept_name',
                    'ancestors',
                    'order_num',
                    'leader',
                    'phone',
                    'email',
                    'status',
                    'update_by',
                );
        return $this
            ->where(atn('dept_id'), '=', get_value($dept, 'dept_id'))
            ->update($values)
            ;
    }

    /**
     * 修改所在部门正常状态
     * 
     * @param int[]|array $deptIds 部门ID组
     */
    public function updateDeptStatusNormal(array $deptIds) {
        return $this
            ->whereIn('dept_id', $deptIds)
            ->update(['status'=>'0'])
            ;
    }

    /**
     * 修改子元素关系
     * 
     * @param SysDeptModel[]|array|Collection $depts 子元素
     * @return 结果
     */
    public function updateDeptChildren(Collection $depts): int {
        return $this
            ->whereIn('dept_id', $depts->map(fn($it)=>$it['deptId']))
            ->update(['ancestors' => DB::raw("case `dept_id` ". $depts->map(fn($it)=>"when {$it['deptId']} then {$it['ancestors']}")->join(',') ." end")])
            ;
    }

    /**
     * 删除部门管理信息
     * 
     * @param $deptId 部门ID
     * @return int 结果
     */
    public function deleteDeptById($deptId): int {
        return $this
            ->where('dept_id', '=', $deptId)
            ->update(['del_flag'=>2])
            ;
    }

    /** 根据DeptId获取 */
    public function selectByDeptId($dept_id): SysDeptModel {
        $where = [['dept_id', '=', "{$dept_id}"]];
        return throw_str(
            static::row($where) ?? "数据($dept_id)为空~"
        );
    }


    /** 获取列表 @return SysDept[]+paginator() */
    public function selectList(int|array $pag=1, array $param=[]): LengthAwarePaginatorProvider {
        return static::rows_pag($pag, [], fn($q)=>$q
                    // ->when(isset($param['dept_id']), fn($q)=>$q->where('dept_id', '=', $param['dept_id']))
                    ->wheres($param, 'dept_id','status','del_flag')
                    ->orderByDesc("dept_id")
        );
    }


    /** 插入数据 */
    public function insertData(array $data): SysDeptModel {
        return throw_str(
            static::row_add([
                // 'dept_id'        => $data['dept_id'],
                'parent_id'         => $data['parent_id'] ?? '0',
                'ancestors'         => $data['ancestors'] ?? '',
                'dept_name'         => $data['dept_name'] ?? '',
                'order_num'         => $data['order_num'] ?? '0',
                'leader'            => $data['leader'] ?? '',
                'phone'             => $data['phone'] ?? '',
                'email'             => $data['email'] ?? '',
                'status'            => $data['status'] ?? '0',
                'del_flag'          => $data['del_flag'] ?? '0',
                'create_by'         => $data['create_by'] ?? '',
                // 'create_time'    => $data['create_time'] ?? '',
                'update_by'         => $data['update_by'] ?? '',
                // 'update_time'    => $data['update_time'] ?? '',
            ])
        );
    }


    /** 更新数据 */
    public function updateData(int|array $idOrWhere, array $data): SysDeptModel {
        $values = static::when(
                    $data, 
                    // 'dept_id',
                    'parent_id',
                    'ancestors',
                    'dept_name',
                    'order_num',
                    'leader',
                    'phone',
                    'email',
                    'status',
                    'del_flag',
                    'create_by',
                    // 'create_time',
                    'update_by',
                    // 'update_time',
                );
        return throw_str(
            static::row_update($idOrWhere, $values)
        );
    }


    /** 删除数据 */
    public function deleteData(int|array $idOrWhere): SysDeptModel {
        return throw_str(
            static::row_delete($idOrWhere)
        );
    }


}